<?php
/**
 * Description: 项目部署的环境变量替换
 *              使用方法： 将此文件放在与.env.example文件同级目录下，执行 php deploy_server.php 即可
 * Created by PhpStorm.
 * User: bililovy
 * Date: 20-5-29
 * Time: 下午2:22
 */
try {
    if (preg_match("/cli/i", php_sapi_name())) {
        //命令行运行
        $baseDir = __DIR__ . DIRECTORY_SEPARATOR;
        $envFile = $baseDir . '.env.template';
        if (is_file($envFile)) {
            // 获取请求参数
            $args = getopt('r:e:h', ['specify::', 'help']);
            if (isset($args[ 'h' ]) || isset($args[ 'help' ])) {
                // 获取帮助信息
                showHelp();
                exit;
            }
            $env = $args[ 'e' ] ?? '';
            $repository = $args[ 'r' ] ?? '';
            if ( ! empty($env) && ! empty($repository)) {
                $configInfo = getDeployConfig($env, $repository);
                if ( ! empty($configInfo)) {
                    $configInfo = array_column($configInfo, null, 'variable_name');
                    /*echo '<pre>';
                    var_dump($configInfo);
                    echo '</pre>';
                    exit;*/
                    // 项目必须要存在模板配置文件
                    $fp = @fopen($envFile, 'r');
                    if ($fp) {
                        $replacedContent = '';
                        while ( ! feof($fp)) {
                            $content = fgets($fp);
                            if (preg_match('/[^\#]/', $content)) {
                                if (preg_match('/\{@@(\w*)@@}/', $content, $matches)) {
                                    $variable = $matches[ 1 ];
                                    $replacedContent .= isset($configInfo[ $variable ]) ? preg_replace('/\{@@(\w*)@@}/', $configInfo[ $variable ][ 'variable_value' ], $content) : $content;
                                } else {
                                    $replacedContent .= $content;
                                }
                            } else {
                                $replacedContent .= $content;
                            }
                        }
                        fclose($fp);
                        $fp = @fopen($baseDir . '.env', 'w+');
                        if ($fp) {
                            fwrite($fp, $replacedContent);
                            fclose($fp);
                        } else {
                            throw new \Exception('环境配置模板文件无法打开，请确认文件权限或文件是否合法');
                        }
                    } else {
                        throw new \Exception('环境配置模板文件无法打开，请确认文件权限或文件是否合法');
                    }
                } else {
                    throw new \Exception('未查询到【' . $repository . '】仓库下【' . $env . '】环境的环境变量配置，请先到工具系统中配置环境变量再尝试执行此命令。可以输入 -h 查看帮助信息');
                }
            } else {
                throw new \Exception('必须指定仓库名和要部署的环境标识，可以输入 -h 查看帮助信息');
            }
        } else {
            throw new \Exception('未发现环境配置模板文件，必须先增加模板文件');
        }
    } else {
        throw new \Exception('环境配置模板文件无法打开，请确认文件权限或文件是否合法');
    }

} catch (\Exception $e) {
    showError($e->getMessage());
}

/**
 * Description: 获取配置数据
 *
 * @param $env
 * @param $repository
 *
 * @return array
 * @throws Exception
 * @Author: Bililovy
 * @Date  : 20-6-2 上午11:14
 */
function getDeployConfig($env, $repository)
{
    $sql = "select `id`,`repository`,`env`,`variable_name`,`variable_value`,`deploy_count` from __TABLE__ where env='{$env}' and repository='{$repository}'";
    $result = dbQuery($sql);
    if ( ! empty($result)) {
        $updateData = [];
        foreach ($result as $item) {
            $updateData[] = [
                'id' => $item[ 'id' ],
                'deploy_count' => $item[ 'deploy_count' ] + 1,
                'latest_use_time' => time()
            ];
        }
        $updateColumn = array_keys($updateData[ 0 ]);
        $referenceColumn = $updateColumn[ 0 ]; //e.g id
        unset($updateColumn[ 0 ]);

        $whereIn = "";
        $sql = "UPDATE __TABLE__ SET ";
        foreach ($updateColumn as $uColumn) {
            $sql .= '`' . $uColumn . "` = CASE ";
            foreach ($updateData as $data) {
                $sql .= "WHEN `" . $referenceColumn . "` = '" . $data[ $referenceColumn ] . "' THEN '" . $data[ $uColumn ] . "' ";
            }
            $sql .= "ELSE `" . $uColumn . "` END, ";
        }
        unset($data);
        foreach ($updateData as $data) {
            $whereIn .= "'" . $data[ $referenceColumn ] . "', ";
        }
        $sql = rtrim($sql, ", ") . " WHERE `" . $referenceColumn . "` IN (" . rtrim($whereIn, ', ') . ")";
        dbUpdate($sql);
    }

    return $result;
}

function getDbConfig()
{
    $dbConfig = [
        'driver' => 'mysql',
        'host' => 'rm-bp1vu65w3gxw1jp7m9o.mysql.rds.aliyuncs.com',
        'port' => 3306,
        'db_name' => 'yx_tools',
        'user' => 'dbwd',
        'password' => 'EO8vBVLPwA2Xclh5tSZM',
    ];

    return new PDO("{$dbConfig['driver']}:host={$dbConfig['host']};port={$dbConfig['port']};dbname={$dbConfig['db_name']}", $dbConfig[ 'user' ], $dbConfig[ 'password' ]);
}

/**
 * Description: 查询数据
 *
 * @param $sql
 * @param string $table
 *
 * @return array
 * @throws Exception
 * @Author: Bililovy
 * @Date  : 20-6-2 上午11:15
 */
function dbQuery($sql, $table = 'yx_deploy_config')
{
    $data = [];
    try {
        $pdo = getDbConfig();
        if ( ! empty($sql)) {
            $sql = str_replace('__TABLE__', $table, $sql);
        }
        $pdo->query("set names utf8");
        //属性名 属性值 数组以关联数组返回
        $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
        $statement = $pdo->query($sql);

        if ($statement) {
            $data = $statement->fetchAll();
        }
        $pdo = null;

        return $data;
    } catch (\Exception $e) {
        throw new \Exception('数据库连接错误：' . $e->getMessage());
    }
}

/**
 * Description: 更新数据
 *
 * @param $sql
 * @param string $table
 *
 * @return bool
 * @throws Exception
 * @Author: Bililovy
 * @Date  : 20-6-2 上午11:15
 */
function dbUpdate($sql, $table = 'yx_deploy_config')
{
    $data = false;
    try {
        $pdo = getDbConfig();
        if ( ! empty($sql)) {
            $sql = str_replace('__TABLE__', $table, $sql);
        }
        $pdo->query("set names utf8");
        //属性名 属性值 数组以关联数组返回
        $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
        $statement = $pdo->exec($sql);

        if ($statement) {
            $data = true;
        }
        $pdo = null;

        return $data;
    } catch (\Exception $e) {
        throw new \Exception('数据库连接错误：' . $e->getMessage());
    }
}


function showHelp()
{
    writeln('');
    writeln(str_repeat('=', 30) . ' 环境变量部署脚本帮助说明 ' . str_repeat('=', 30));
    writeln('');
    writeln("脚本支持参数：\t-e\t[string]\t传入要部署的环境，如：local，dev，qa1，qa2等");
    writeln("\t\t\t\t\t" . '环境名称可以再系统工具：https://team-tool.01y.com中配置，配置后在此传入对应环境名即可应用次环境变量配置');
    writeln("\t\t-r\t[string]\t传入要部署的代码仓库名，如：yx_new_boss，yx_search_service等");
    writeln("\t\t\t\t\t" . '仓库名可以再系统工具：https://team-tool.01y.com中配置，配置后在此传入对应环境名即可应用次环境变量配置');
    writeln("\t\t-h\t[string]\t查看帮助信息");
    writeln("\t\t--help\t[string]\t查看帮助信息");
    writeln('');
    writeln(str_repeat('=', 30) . ' 环境变量部署脚本帮助说明 ' . str_repeat('=', 30));
    writeln('');
}

function writeln($message)
{
    echo "{$message}\n";
}

function showError($message)
{
    writeln('');
    writeln(str_repeat('=', 30) . ' 脚本运行错误信息 ' . str_repeat('=', 30));
    writeln('');
    writeln('脚本运行出现错误：' . $message);
    writeln('');
    writeln(str_repeat('=', 30) . ' 脚本运行错误信息 ' . str_repeat('=', 30));
    writeln('');
}
